/*
 * 文件名：Configurator.java
 * 版权：Copyright by www.wootide.com
 * 描述：
 * 修改人：qianfm
 * 修改时间：Sep 24, 2012
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */
package com.wootide.cms.common.manager;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;


/**
 * 〈系统初始读取配置文件〉
 * 〈功能详细描述〉
 * @author qianfm
 * @version Sep 24, 2012
 * @see Configurator
 * @since
 */

public class Configurator
{
    
    /**
     * 加载log4j配置.
     * 
     * @param configFile
     *            {@link String} log4j的配置文件（properties或xml），可以 是绝对路径（如
     *            d:\project\etc\log4j.properties）， 也可以是CLASS_PATH下的包名格式的资源名
     *            （如resource.config.log4j.properties）
     * @throws Exception
     *             指定的配置文件不存在或解析异常
     */
    public static void configLog4j(boolean needWatch, String configFile)
            throws Exception
    {
        configLog4j(needWatch, new String[] {configFile});
    }
    
    /**
     * 加载log4j配置.
     * 
     * @param configFiles
     *            {@link String}[] log4j的配置文件（properties或xml），可以 是绝对路径（如
     *            d:\project\etc\log4j.properties）， 也可以是CLASS_PATH下的包名格式的资源名
     *            （如resource.config.log4j.properties）
     * @throws Exception
     *             指定的配置文件不存在或解析异常
     */
    public static void configLog4j(boolean needWatch, String... configFiles)
            throws Exception
    {
        if (configFiles == null || configFiles.length < 1)
        {
            throw new Exception("no log4j config file defined");
        }
        else
        {
            for (String configFile : configFiles)
            {
                String localPath = GeneralUtils.toLocalFilePath(configFile);
                if (localPath.indexOf(File.separator) > -1)
                {
                    // absolute file path
                    if (!new File(localPath).exists())
                    {
                        throw new FileNotFoundException(
                                "log4j config file not " + "found : "
                                        + configFile);
                    }
                    final long defaultDelay = 1000L;
                    if (localPath.toLowerCase().endsWith(".properties"))
                    {
                        // properties file
                        if (needWatch)
                        {
                            PropertyConfigurator.configureAndWatch(localPath,
                                    defaultDelay);
                        }
                        else
                        {
                            PropertyConfigurator.configure(localPath);
                        }
                    }
                    else if (localPath.toLowerCase().endsWith(".xml"))
                    {
                        // xml file
                        if (needWatch)
                        {
                            DOMConfigurator.configureAndWatch(localPath,
                                    defaultDelay);
                        }
                        else
                        {
                            DOMConfigurator.configure(localPath);
                        }
                    }
                }
                else
                {
                    // class path resource
                    if (localPath.toLowerCase().endsWith(".properties"))
                    {
                        // properties file
                        try
                        {
                            PropertyConfigurator.configure(getProp(configFile.substring(0,
                                    localPath.toLowerCase()
                                            .indexOf(".properties"))));
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("log4j config file not "
                                    + "found : " + configFile, ex);
                            
                        }
                    }
                    else if (localPath.toLowerCase().endsWith(".xml"))
                    {
                        // xml file
                        String suffix = localPath.substring(localPath.toLowerCase()
                                .lastIndexOf(".xml"));
                        try
                        {
                            DOMConfigurator.configure(DocumentBuilderFactory.newInstance()
                                    .newDocumentBuilder()
                                    .parse(Configurator.class.getClassLoader()
                                            .getResourceAsStream(localPath.substring(0,
                                                    localPath.toLowerCase()
                                                            .lastIndexOf(".xml"))
                                                    .replace(".",
                                                            File.separator)
                                                    + suffix))
                                    .getDocumentElement());
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("failed to load log4j config"
                                    + " file : " + configFile, ex);
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 加载spring配置.
     * 
     * @param configFile
     *            {@link String} spring的配置文件（xml），可以 是绝对路径（如
     *            d:\project\etc\spring.xml）， 也可以是CLASS_PATH下的包名格式的资源名
     *            （如resource.config.spring.xml）
     * @return {@link ApplicationContext} spring的上下文
     * @throws Exception
     *             配置加载异常
     */
    public static ApplicationContext configSpring(String configFile)
            throws Exception
    {
        return configSpring(new String[] {configFile});
    }
    
    /**
     * 尝试从claspath加载spring配置文件.
     * 
     * @param springClasspathResources .
     * @return instance of ApplicationContext.
     */
    public static ApplicationContext configSpringByClassPath(
            String... springClasspathResources) throws Exception
    {
        ApplicationContext context = null;
        try
        {
            
            context = new ClassPathXmlApplicationContext(
                    springClasspathResources, true, context);
            
        }
        catch (Exception ex)
        {
            throw new Exception("failed to load spring class-path config file",
                    ex);
        }
        return context;
    }
    
    /**
     * 加载spring配置.
     * 
     * @param configFiles
     *            {@link String}[] spring的配置文件（xml），可以 是绝对路径（如
     *            d:\project\etc\spring.xml）， 也可以是CLASS_PATH下的包名格式的资源名
     *            （如resource.config.spring.xml）
     * @return {@link ApplicationContext} spring的上下文
     * @throws Exception
     *             配置加载异常
     */
    public static ApplicationContext configSpring(String... configFiles)
            throws Exception
    {
        if (configFiles == null || configFiles.length < 1)
        {
            throw new Exception("no spring config file defined");
        }
        List<String> configFileListOfFileSystem = new ArrayList<String>();
        List<String> configFileListOfClassPath = new ArrayList<String>();
        for (String configFile : configFiles)
        {
            if (!StringUtils.isEmpty(configFile))
            {
                String localPath = GeneralUtils.toLocalFilePath(configFile);
                if (localPath.indexOf(File.separator) > -1)
                {
                    // absolute file path
                    if (!new File(localPath).exists())
                    {
                        throw new FileNotFoundException(
                                "spring config file not " + "found : "
                                        + configFile);
                    }
                    configFileListOfFileSystem.add(File.separator
                            + File.separator + localPath);
                }
                else
                {
                    // class path resource
                    String suffix = localPath.substring(localPath.toLowerCase()
                            .lastIndexOf(".xml"));
                    localPath = localPath.substring(0,
                            localPath.toLowerCase().lastIndexOf(".xml"))
                            .replace(".", File.separator)
                            + suffix;
                    configFileListOfClassPath.add(localPath);
                }
            }
        }
        ApplicationContext context = null;
        try
        {
            if (configFileListOfClassPath.size() > 0)
            {
                context = new ClassPathXmlApplicationContext(
                        configFileListOfClassPath.toArray(new String[0]), true,
                        context);
            }
        }
        catch (Exception ex)
        {
            throw new Exception("failed to load spring class-path config file",
                    ex);
        }
        try
        {
            if (configFileListOfFileSystem.size() > 0)
            {
                context = new FileSystemXmlApplicationContext(
                        configFileListOfFileSystem.toArray(new String[0]),
                        true, context);
            }
        }
        catch (Exception ex)
        {
            throw new Exception(
                    "failed to load spring file-system config file", ex);
        }
        return context;
    }
    
    /**
     * 构造函数.
     * 
     */
    private Configurator()
    {
        
    }
    
    /**
     * 
     * Description: 获取Properties<br>
     * Implement: <br>
     * @param fileName
     * @return
     * @see
     * @return Properties
     * @author qianfm
     */
    private static Properties getProp(String fileName) throws IOException
    {
        Properties prop = new Properties();
        
        InputStream inputStream = FileUtils.openInputStream(new File(
                getFilename(fileName)));
        if (inputStream != null)
        {
            prop.load(inputStream);
        }
        else
        {
            prop = null;
        }
        return prop;
    }
    
    /**
     * 转换包形式的属性文件名为URI.
     * 
     * @param filename String 包形式的属性文件名
     * @return String 对应的URI
     */
    private static String getFilename(String filename)
    {
        String name = filename.replace(".", File.separator);
        name += ".properties";
        return name;
    }
    
    public static void main(String[] args)
    {
        try
        {
            Properties prop = getProp("C:/Users/qianfm/sis/conf/db");
            System.out.println(prop.getProperty("jdbc.username"));
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}
